package com.wlcorp.forcazamis.business.confirm.impl;

import java.util.Iterator;
import java.util.List;

import com.wlcorp.forcazamis.business.confirm.IConfirmService;
import com.wlcorp.forcazamis.dao.baseinfo.IDepotDAO;
import com.wlcorp.forcazamis.dao.confirm.IConfirmDAO;
import com.wlcorp.forcazamis.dao.confirm.IConfirmDetailDAO;
import com.wlcorp.forcazamis.dao.pi.IPidetailDAO;
import com.wlcorp.forcazamis.dao.sample.ISubSampleAssignDAO;
import com.wlcorp.forcazamis.dao.stock.IStockDAO;
import com.wlcorp.forcazamis.dao.storageassign.IStorageAssignDAO;
import com.wlcorp.forcazamis.dao.storagein.IStorageInDAO;
import com.wlcorp.forcazamis.dao.storageout.IStorageOutDAO;
import com.wlcorp.forcazamis.dao.system.IDepartmentDAO;
import com.wlcorp.forcazamis.dao.system.IStaffDAO;
import com.wlcorp.forcazamis.domain.baseinfo.Depot;
import com.wlcorp.forcazamis.domain.confirm.Confirm;
import com.wlcorp.forcazamis.domain.confirm.ConfirmDetail;
import com.wlcorp.forcazamis.domain.pi.Pidetail;
import com.wlcorp.forcazamis.domain.sample.SubSampleAssign;
import com.wlcorp.forcazamis.domain.stock.Stock;
import com.wlcorp.forcazamis.domain.storageassign.StorageAssign;
import com.wlcorp.forcazamis.domain.storageassign.StorageAssignSample;
import com.wlcorp.forcazamis.domain.storagein.StorageIn;
import com.wlcorp.forcazamis.domain.storagein.StorageInSample;
import com.wlcorp.forcazamis.domain.storageout.StorageOut;
import com.wlcorp.forcazamis.domain.storageout.StorageOutSample;
import com.wlcorp.forcazamis.domain.system.Department;
import com.wlcorp.forcazamis.domain.system.Staff;
import com.wlcorp.forcazamis.exception.ServiceException;
import com.wlcorp.forcazamis.sys.BaseService;
import com.wlcorp.forcazamis.sys.util.AppConstant;

public class ConfirmServiceImpl extends BaseService implements IConfirmService {
	
	private IConfirmDAO confirmDAO;
	private IConfirmDetailDAO confirmDetailDAO;
	private IDepotDAO depotDAO;
	private IStaffDAO staffDAO;
	private IStorageInDAO storageInDAO;
	private IStorageOutDAO storageOutDAO;
	private IStorageAssignDAO storageAssignDAO;
	private ISubSampleAssignDAO subSampleAssignDAO;
	private IDepartmentDAO departmentDAO;
	private IPidetailDAO pidetailDAO;
	private IStockDAO stockDAO;
	private Object mutex = new Object();
	public List<Confirm> getConfirmList(Confirm confirm) throws ServiceException {
		return confirmDAO.getConfirmList(confirm);
	}

	public Long getConfirmCount(Confirm confirm) throws ServiceException {
		return confirmDAO.getConfirmCount(confirm);
	}

	public Confirm getConfirmById(Long confirmId) throws ServiceException {
		if(null == confirmId){
			return null;
		}
		return confirmDAO.getConfirmById(confirmId);
	}

	public void deleteConfirm(Confirm confirm) throws ServiceException {
		confirmDAO.deleteConfirm(confirm);
	}

	public void setDepartmentDAO(IDepartmentDAO departmentDAO) {
		this.departmentDAO = departmentDAO;
	}

	public void setPidetailDAO(IPidetailDAO pidetailDAO) {
		this.pidetailDAO = pidetailDAO;
	}
	
	

	public void saveConfirm(Confirm confirm) throws ServiceException {
		if(null == confirm.getConfirmId()){
			if(AppConstant.CONFIRM_TYPE_IN_STORAGE == confirm.getConfirmType()){
				Depot depot = depotDAO.getDepotById(AppConstant.DEPOT_ID_SAMPLE);
				confirm.setNextConfirmer(depot.getManager());
				StorageIn storageIn = storageInDAO.getStorageInById(confirm.getItemId());
				storageIn.setState(AppConstant.BILL_STATE_PRE_CONFIRM);
				storageInDAO.saveStorageIn(storageIn);
			} else if(AppConstant.CONFIRM_TYPE_OUT_STORAGE == confirm.getConfirmType()){
				Depot depot = depotDAO.getDepotById(AppConstant.DEPOT_ID_SAMPLE);
				confirm.setNextConfirmer(depot.getManager());
				StorageOut storageOut = storageOutDAO.getStorageOutById(confirm.getItemId());
				storageOut.setState(AppConstant.BILL_STATE_PRE_CONFIRM);
				storageOutDAO.saveStorageOut(storageOut);
			} else if(AppConstant.CONFIRM_TYPE_ASSIGN_STORAGE == confirm.getConfirmType()){
				StorageAssign storageAssign = storageAssignDAO.getStorageAssignById(confirm.getItemId());
				confirm.setNextConfirmer(storageAssign.getAssignToStaff());
				storageAssign.setState(AppConstant.ASSIGN_STATE_CONFIRMING);
				storageAssignDAO.saveStorageAssign(storageAssign);
			} else if(AppConstant.CONFIRM_TYPE_PI == confirm.getConfirmType()){//PI提交审批
				Pidetail pidetail = pidetailDAO.getPidetailById(confirm.getItemId());
				pidetail.setState(AppConstant.BILL_STATE_PRE_CONFIRM);
				Department businessDepart = departmentDAO.getDepartmentByFlag(AppConstant.DEPART_FLAG_BUSINESS);//业务部
				confirm.setNextConfirmer(businessDepart.getManager());
				pidetailDAO.savePidetail(pidetail);
			}else if(AppConstant.CONFIRM_TYPE_STOCK == confirm.getConfirmType()){//采购合同提交审批
				Stock stock=stockDAO.getStockById(confirm.getItemId());
				stock.setState(AppConstant.BILL_STATE_PRE_CONFIRM);
				Department businessDepart = departmentDAO.getDepartmentByFlag(AppConstant.DEPART_FLAG_BUSINESS);//业务部
				confirm.setNextConfirmer(businessDepart.getManager());
				stockDAO.saveStock(stock);
			}
		}
		confirmDAO.saveConfirm(confirm);
	}

	public void setConfirmDAO(IConfirmDAO confirmDAO) {
		this.confirmDAO = confirmDAO;
	}

	public void setDepotDAO(IDepotDAO depotDAO) {
		this.depotDAO = depotDAO;
	}

	public void setConfirmDetailDAO(IConfirmDetailDAO confirmDetailDAO) {
		this.confirmDetailDAO = confirmDetailDAO;
	}
	
	public void setStaffDAO(IStaffDAO staffDAO) {
		this.staffDAO = staffDAO;
	}
	
	public void setSubSampleAssignDAO(ISubSampleAssignDAO subSampleAssignDAO) {
		this.subSampleAssignDAO = subSampleAssignDAO;
	}

	public void setStorageInDAO(IStorageInDAO storageInDAO) {
		this.storageInDAO = storageInDAO;
	}

	public void setStorageOutDAO(IStorageOutDAO storageOutDAO) {
		this.storageOutDAO = storageOutDAO;
	}
	
	public void setStorageAssignDAO(IStorageAssignDAO storageAssignDAO) {
		this.storageAssignDAO = storageAssignDAO;
	}
	
	public void setStockDAO(IStockDAO stockDAO) {
		this.stockDAO = stockDAO;
	}

	public void saveConfirmDetail(ConfirmDetail confirmDetail) throws ServiceException {
		if(null != confirmDetail.getConfirmId()){
			Confirm confirm = confirmDAO.getConfirmById(confirmDetail.getConfirmId());
			confirmDetail.setConfirm(confirm);
			if(AppConstant.CONFIRM_TYPE_IN_STORAGE == confirm.getConfirmType()){
				confirmStorageIn(confirm,confirmDetail);
			} else if(AppConstant.CONFIRM_TYPE_OUT_STORAGE == confirm.getConfirmType()){
				confirmStorageOut(confirm,confirmDetail);
			} else if(AppConstant.CONFIRM_TYPE_ASSIGN_STORAGE == confirm.getConfirmType()){
				confirmStorageAssign(confirm,confirmDetail);
			} else if(AppConstant.CONFIRM_TYPE_PI == confirm.getConfirmType()){//PI审批
				confirmPI(confirm,confirmDetail);
			}else if(AppConstant.CONFIRM_TYPE_STOCK == confirm.getConfirmType()){//采购合同审批
				confirmStock(confirm,confirmDetail);
			}
			
			if(AppConstant.BASE_BEAN_STATUS_ERROR == confirmDetail.getStatus()){
				return;
			}
			confirmDAO.saveConfirm(confirm);
		}
		if(null != confirmDetail.getConfirmerId()){
			confirmDetail.setConfirmer(staffDAO.getStaffById(confirmDetail.getConfirmerId()));
		}
		confirmDetailDAO.saveConfirmDetail(confirmDetail);
	}

	public List<ConfirmDetail> getConfirmDetailList(ConfirmDetail confirmDetail) throws ServiceException {
		return confirmDetailDAO.getConfirmDetailList(confirmDetail);
	}

	public Object getItem(Long itemId,Integer itemType) throws ServiceException {
		Object obj = null;
		if(AppConstant.CONFIRM_TYPE_IN_STORAGE == itemType){
			obj = storageInDAO.getStorageInById(itemId);
		} else if(AppConstant.CONFIRM_TYPE_OUT_STORAGE == itemType){
			obj = storageOutDAO.getStorageOutById(itemId);
		} else if(AppConstant.CONFIRM_TYPE_ASSIGN_STORAGE == itemType){
			obj = storageAssignDAO.getStorageAssignById(itemId);
		} else if(AppConstant.CONFIRM_TYPE_PI == itemType){
			obj = pidetailDAO.getPidetailById(itemId);
		} else if(AppConstant.CONFIRM_TYPE_STOCK == itemType){
			obj = stockDAO.getStockById(itemId);
		}
		return obj;
	}
	
	private void confirmStorageIn(Confirm confirm,ConfirmDetail confirmDetail){
//		入库
		StorageIn storageIn = storageInDAO.getStorageInById(confirm.getItemId());
		StorageIn tmpStorageIn = storageInDAO.getStorageInById(confirm.getItemId());
		if(AppConstant.CONFIRM_RESULT_PASS == confirmDetail.getConfirmResult()){
			for(Iterator<?> iter = storageIn.getStorageInSampleSet().iterator();iter.hasNext();){
				StorageInSample storageInSample = (StorageInSample)iter.next();
				SubSampleAssign subSampleAssign = new SubSampleAssign();
				subSampleAssign.setOwnerId(AppConstant.DEPOT_ID_SAMPLE);
				subSampleAssign.setSubSampleId(storageInSample.getSubSample().getSubSampleId());
				subSampleAssign = subSampleAssignDAO.getSubSampleAssignBySubSampleAndOwner(subSampleAssign);
				if(null == subSampleAssign){
					subSampleAssign = new SubSampleAssign();
				}
				subSampleAssign.setOwner(depotDAO.getDepotById(AppConstant.DEPOT_ID_SAMPLE));
				subSampleAssign.setSubSample(storageInSample.getSubSample());
				if(null == subSampleAssign.getSampleCount()){
					subSampleAssign.setSampleCount(0L);
				}
				subSampleAssign.setSampleCount(subSampleAssign.getSampleCount() + storageInSample.getInCount());
				subSampleAssignDAO.saveSubSampleAssign(subSampleAssign);
			}
			tmpStorageIn.setState(AppConstant.BILL_STATE_CONFIRMED);
			confirm.setState(AppConstant.CONFIRM_STATE_CONFIRMED);
		}else{
			tmpStorageIn.setState(AppConstant.BILL_STATE_SUBMITED);
		}
		tmpStorageIn.setConfirm(confirm);
		storageInDAO.saveStorageIn(tmpStorageIn);
		confirm.setResult(confirmDetail.getConfirmResult());
	}
	
	private void confirmStorageOut(Confirm confirm,ConfirmDetail confirmDetail){
		//出库，出库必须防止并发导致的库存小于0的情况
		synchronized (mutex) {
			StorageOut tmpStorageOut = storageOutDAO.getStorageOutById(confirm.getItemId());
			StorageOut storageOut = storageOutDAO.getStorageOutById(confirm.getItemId());
			if(AppConstant.CONFIRM_RESULT_PASS == confirmDetail.getConfirmResult()){
				for(Iterator<?> iter = storageOut.getStorageOutSampleSet().iterator();iter.hasNext();){
					StorageOutSample storageOutSample = (StorageOutSample)iter.next();
					SubSampleAssign subSampleAssign = new SubSampleAssign();
					subSampleAssign.setOwnerId(AppConstant.DEPOT_ID_SAMPLE);
					subSampleAssign.setSubSampleId(storageOutSample.getSubSample().getSubSampleId());
					subSampleAssign = subSampleAssignDAO.getSubSampleAssignBySubSampleAndOwner(subSampleAssign);
					if(null == subSampleAssign || null == subSampleAssign.getSampleCount() 
							|| subSampleAssign.getSampleCount() - storageOutSample.getOutCount() < 0){
						long remainCount = 0;
						if(null != subSampleAssign && null != subSampleAssign.getSampleCount()){
							remainCount = subSampleAssign.getSampleCount();
						}
						setErrorField(confirmDetail,AppConstant.BASE_BEAN_STATUS_ERROR,
								"样品库中样品颜色“" 
								+  storageOutSample.getSubSample().getCcolorDesc() 
								+ "”的样品剩余库存" + remainCount + "个，少于" + storageOutSample.getOutCount() + "个！");
						return;
					}
					subSampleAssign.setSampleCount(subSampleAssign.getSampleCount() - storageOutSample.getOutCount());
					subSampleAssignDAO.saveSubSampleAssign(subSampleAssign);
					
				}
				tmpStorageOut.setState(AppConstant.BILL_STATE_CONFIRMED);
				confirm.setState(AppConstant.CONFIRM_STATE_CONFIRMED);
			}else{
				tmpStorageOut.setState(AppConstant.BILL_STATE_SUBMITED);
			}
			tmpStorageOut.setConfirm(confirm);
			storageOutDAO.saveStorageOut(tmpStorageOut);
			confirm.setResult(confirmDetail.getConfirmResult());
		}
	}
	
	private void confirmStorageAssign(Confirm confirm,ConfirmDetail confirmDetail){
		synchronized (mutex) {
			StorageAssign storageAssign = storageAssignDAO.getStorageAssignById(confirm.getItemId());
			if(AppConstant.CONFIRM_RESULT_PASS == confirmDetail.getConfirmResult()){
				Depot fromDepot = storageAssign.getAssignFromDepot();
				Depot toDepot = storageAssign.getAssignToDepot();

				for(Iterator<?> iter = storageAssign.getStorageAssignSampleSet().iterator();iter.hasNext();){
					StorageAssignSample storageAssignSample = (StorageAssignSample)iter.next();
					SubSampleAssign fromSubSampleAssign = new SubSampleAssign();
					fromSubSampleAssign.setSubSampleId(storageAssignSample.getSubSample().getSubSampleId());
					fromSubSampleAssign.setOwnerId(fromDepot.getDepotId());
					fromSubSampleAssign = subSampleAssignDAO.getSubSampleAssignBySubSampleAndOwner(fromSubSampleAssign);
					
					SubSampleAssign toSubSampleAssign = new SubSampleAssign();
					toSubSampleAssign.setSubSampleId(storageAssignSample.getSubSample().getSubSampleId());
					toSubSampleAssign.setOwnerId(toDepot.getDepotId());
					toSubSampleAssign.setOwner(toDepot);
					toSubSampleAssign = subSampleAssignDAO.getSubSampleAssignBySubSampleAndOwner(toSubSampleAssign);
					
					if(null == fromSubSampleAssign || null == fromSubSampleAssign.getSampleCount() ||
							fromSubSampleAssign.getSampleCount() < storageAssignSample.getAssignCount()){
						long remainCount = 0;
						if(null != fromSubSampleAssign && null != fromSubSampleAssign.getSampleCount()){
							remainCount = fromSubSampleAssign.getSampleCount();
						}
						setErrorField(confirmDetail,AppConstant.BASE_BEAN_STATUS_ERROR,
								fromDepot.getDepotName() + "中样品颜色“" 
								+  storageAssignSample.getSubSample().getCcolorDesc() 
								+ "”的样品当前库存" + remainCount + "个，少于" + storageAssignSample.getAssignCount() + "个！");
						return;
					}
					if(null == toSubSampleAssign){
						toSubSampleAssign = new SubSampleAssign();
						toSubSampleAssign.setSubSample(storageAssignSample.getSubSample());
						toSubSampleAssign.setOwner(toDepot);
						toSubSampleAssign.setSampleCount(0L);
					}
					//System.out.println("fromSubSampleAssign.getSampleCount = " + fromSubSampleAssign.getSampleCount());
					fromSubSampleAssign.setSampleCount(fromSubSampleAssign.getSampleCount() - storageAssignSample.getAssignCount());
					toSubSampleAssign.setSampleCount(toSubSampleAssign.getSampleCount() + storageAssignSample.getAssignCount());
					subSampleAssignDAO.saveSubSampleAssign(fromSubSampleAssign);
					subSampleAssignDAO.saveSubSampleAssign(toSubSampleAssign);
				}
				confirm.setState(AppConstant.CONFIRM_STATE_CONFIRMED);
				storageAssign.setState(AppConstant.ASSIGN_STATE_CONFIRMED);
			}else{
				storageAssign.setState(AppConstant.ASSIGN_STATE_SUBMITED);
			}
			storageAssign.setConfirm(confirm);
			storageAssignDAO.saveStorageAssign(storageAssign);
			confirm.setResult(confirmDetail.getConfirmResult());
		}
	}
	
	private void confirmPI(Confirm confirm,ConfirmDetail confirmDetail){
		Pidetail pidetail = pidetailDAO.getPidetailById(confirm.getItemId());
		if(AppConstant.CONFIRM_RESULT_PASS == confirmDetail.getConfirmResult()){
			Department financeDepart = departmentDAO.getDepartmentByFlag(AppConstant.DEPART_FLAG_FINANCE);//财务部
			Staff financeManager = financeDepart.getManager();

			if(financeManager.getStaffId().equals(confirm.getNextConfirmer().getStaffId())){//财务部经理审批后则审批结束
				confirm.setState(AppConstant.CONFIRM_STATE_CONFIRMED);
				pidetail.setState(AppConstant.BILL_STATE_CONFIRMED);
			}else{
				confirm.setState(AppConstant.BILL_STATE_PRE_CONFIRM);
				pidetail.setState(AppConstant.BILL_STATE_PRE_CONFIRM);
				//设置下一审核人为财务部经理
				confirm.setNextConfirmer(financeManager);
			}
		}else{//审批未通过
			pidetail.setState(AppConstant.BILL_STATE_SUBMITED);
		}
		pidetail.setConfirm(confirm);
		pidetailDAO.savePidetail(pidetail);
		confirm.setResult(confirmDetail.getConfirmResult());
	}
	
	private void confirmStock(Confirm confirm,ConfirmDetail confirmDetail){
		Stock stock = stockDAO.getStockById(confirm.getItemId());
		if(AppConstant.CONFIRM_RESULT_PASS == confirmDetail.getConfirmResult()){
			Department financeDepart = departmentDAO.getDepartmentByFlag(AppConstant.DEPART_FLAG_FINANCE);//财务部
			Staff financeManager = financeDepart.getManager();

			if(financeManager.getStaffId().equals(confirm.getNextConfirmer().getStaffId())){//财务部经理审批后则审批结束
				confirm.setState(AppConstant.CONFIRM_STATE_CONFIRMED);
				stock.setState(AppConstant.BILL_STATE_CONFIRMED);
			}else{
				confirm.setState(AppConstant.BILL_STATE_PRE_CONFIRM);
				stock.setState(AppConstant.BILL_STATE_PRE_CONFIRM);
				//设置下一审核人为财务部经理
				confirm.setNextConfirmer(financeManager);
			}
		}else{//审批未通过
			stock.setState(AppConstant.BILL_STATE_SUBMITED);
		}
		stock.setConfirm(confirm);
		stockDAO.saveStock(stock);
		confirm.setResult(confirmDetail.getConfirmResult());
	}
}
